// fast4j - Fast & Agile Service Tools for Java
// Copyright (C) 2007 Alexandre ROMAN
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

// $Id: WebApplicationCreator.java 94 2007-05-13 19:44:05Z alexandre.roman $

package fast4j.ace.extensions.web;

import java.io.File;
import java.util.Map;
import java.util.ResourceBundle;

import org.apache.commons.io.FileUtils;

import fast4j.ace.ApplicationDescriptor;
import fast4j.ace.PropertyDescriptor;
import fast4j.ace.impl.AbstractGroovyApplicationCreator;

/**
 * Web application creator. Creates a JEE web application archive (WAR).
 * <p>
 * Supported properties:
 * </p>
 * <ul>
 * <li><strong>ui</strong>: User interface (<code>myfaces</code>,
 * <code>struts1</code>, <code>struts2</code>)</li>
 * <li><strong>uiVersion</strong>: User interface library version</li>
 * </ul>
 * @author alexandre.roman
 */
public class WebApplicationCreator extends AbstractGroovyApplicationCreator {
    private static final ResourceBundle RESOURCES = ResourceBundle
            .getBundle(WebApplicationCreator.class.getPackage().getName()
                    + ".Resources");
    
    public WebApplicationCreator() {
        super();
        
        supportedProperties.add(new PropertyDescriptor("ui", RESOURCES
                .getString("web.property.ui"), "myfaces"));
        supportedProperties.add(new PropertyDescriptor("uiVersion", RESOURCES
                .getString("web.property.uiVersion"), "1.1.5"));
    }
    
    @Override
    protected void doCreate(ApplicationDescriptor desc, File dir)
            throws Exception {
        // initialize bindings
        final Map<String, String> bindings = createBindings(desc);
        bindings.put("id", desc.getId());
        bindings.put("name", desc.getName());
        bindings.put("version", desc.getVersion());
        bindings.put("rootPackage", desc.getRootPackage());
        
        // alias for struts -> struts1
        if ("struts".equals(bindings.get("ui"))) {
            bindings.put("ui", "struts1");
        }
        
        final File baseDir = new File(dir, desc.getId());
        final File pomFile = new File(baseDir, "pom.xml");
        log.info("Creating pom.xml");
        writeToFile(pomFile, "pom.xml.template", bindings);
        
        final File srcMainWebapp = new File(baseDir, "src/main/webapp");
        final File webXml = new File(srcMainWebapp, "WEB-INF/web.xml");
        log.info("Creating web.xml");
        writeToFile(webXml, "web.xml.template", bindings);
        
        final File srcMainJava = new File(baseDir, "src/main/java");
        final File srcTestJava = new File(baseDir, "src/test/java");
        final File srcMainResources = new File(baseDir, "src/main/resources");
        final File srcTestResources = new File(baseDir, "src/test/resources");
        final File rootJavaPackage = new File(srcMainJava, desc
                .getRootPackage().replace('.', '/'));
        final File webJavaPackage = new File(rootJavaPackage, "web");
        
        FileUtils.forceMkdir(srcTestJava);
        
        final File howto = new File(baseDir, "HOWTO.txt");
        log.info("Creating HOWTO.txt");
        FileUtils.copyURLToFile(getClass().getResource("HOWTO.txt"), howto);
        
        final File log4j = new File(srcTestResources, "log4j.properties");
        log.info("Creating log4j.properties");
        writeToFile(log4j, "log4j.properties.template", bindings);
        
        final File srcMainConfig = new File(baseDir, "src/main/config");
        final File contextXml = new File(srcMainConfig, "context.xml");
        log.info("Creating context.xml");
        writeToFile(contextXml, "context.xml.template", bindings);
        
        final File styles = new File(srcMainWebapp, "css/styles.css");
        log.info("Creating styles.css");
        FileUtils.copyURLToFile(getClass().getResource("styles.css"), styles);
        
        final String ui = bindings.get("ui");
        if ("myfaces".equals(ui)) {
            final File facesConfig = new File(srcMainWebapp,
                    "WEB-INF/faces-config.xml");
            log.info("Creating faces-config.xml");
            writeToFile(facesConfig, "myfaces/faces-config.xml.template",
                bindings);
            
            // required for using Tomahawk components with Facelets
            final File tomahawkTaglib = new File(srcMainResources,
                    "META-INF/tomahawk.taglib.xml");
            log.info("Creating tomahawk.taglib.xml");
            FileUtils.copyURLToFile(getClass().getResource(
                "myfaces/tomahawk.taglib.xml"), tomahawkTaglib);
            
            final File helloBean = new File(webJavaPackage, "HelloBean.java");
            log.info("Creating HelloBean.java");
            writeToFile(helloBean, "myfaces/HelloBean.java.template", bindings);
            
            final File index = new File(srcMainWebapp, "index.xhtml");
            log.info("Creating index.xhtml");
            writeToFile(index, "myfaces/index.xhtml.template", bindings);
            
            // required for proper redirection
            final File indexJsp = new File(srcMainWebapp, "index.jsp");
            log.info("Creating index.jsp");
            FileUtils.copyURLToFile(
                getClass().getResource("myfaces/index.jsp"), indexJsp);
        }
        
        if ("struts1".equals(ui)) {
            final File strutsConfig = new File(srcMainWebapp,
                    "WEB-INF/struts-config.xml");
            log.info("Creating struts-config.xml");
            writeToFile(strutsConfig, "struts1/struts-config.xml.template",
                bindings);
            
            final File actionContext = new File(srcMainWebapp,
                    "WEB-INF/spring/action-context.xml");
            log.info("Creating action-context.xml");
            writeToFile(actionContext, "struts1/action-context.xml.template",
                bindings);
            
            final File helloAction = new File(webJavaPackage,
                    "HelloAction.java");
            log.info("Creating HelloAction.java");
            writeToFile(helloAction, "struts1/HelloAction.java.template",
                bindings);
            
            final File helloForm = new File(webJavaPackage, "HelloForm.java");
            log.info("Creating HelloForm.java");
            writeToFile(helloForm, "struts1/HelloForm.java.template", bindings);
            
            final File helloJsp = new File(srcMainWebapp,
                    "WEB-INF/jsp/pages/hello.jsp");
            log.info("Creating hello.jsp");
            writeToFile(helloJsp, "struts1/hello.jsp.template", bindings);
            
            final File indexJsp = new File(srcMainWebapp, "index.jsp");
            log.info("Creating index.jsp");
            FileUtils.copyURLToFile(
                getClass().getResource("struts1/index.jsp"), indexJsp);
            
            final File taglibsJsp = new File(srcMainWebapp,
                    "WEB-INF/jsp/inc/taglibs.jsp");
            log.info("Creating taglibs.jsp");
            FileUtils.copyURLToFile(getClass().getResource(
                "struts1/taglibs.jsp"), taglibsJsp);
        }
        
        if ("struts2".equals(ui)) {
            final File strutsXml = new File(srcMainResources, "struts.xml");
            log.info("Creating struts.xml");
            writeToFile(strutsXml, "struts2/struts.xml.template", bindings);
            
            final File actionContext = new File(srcMainWebapp,
                    "WEB-INF/spring/action-context.xml");
            log.info("Creating action-context.xml");
            writeToFile(actionContext, "struts2/action-context.xml.template",
                bindings);
            
            final File helloAction = new File(webJavaPackage,
                    "HelloAction.java");
            log.info("Creating HelloAction.java");
            writeToFile(helloAction, "struts2/HelloAction.java.template",
                bindings);
            
            final File helloJsp = new File(srcMainWebapp, "hello.jsp");
            log.info("Creating hello.jsp");
            writeToFile(helloJsp, "struts2/hello.jsp.template", bindings);
            
            final File indexJsp = new File(srcMainWebapp, "index.jsp");
            log.info("Creating index.jsp");
            FileUtils.copyURLToFile(
                getClass().getResource("struts2/index.jsp"), indexJsp);
            
            final File taglibsJsp = new File(srcMainWebapp,
                    "WEB-INF/jsp/inc/taglibs.jsp");
            log.info("Creating taglibs.jsp");
            FileUtils.copyURLToFile(getClass().getResource(
                "struts2/taglibs.jsp"), taglibsJsp);
        }
        
        final File serviceContext = new File(srcMainWebapp,
                "WEB-INF/spring/service-context.xml");
        log.info("Creating service-context.xml");
        writeToFile(serviceContext, "service-context.xml.template", bindings);
        
        final File helloService = new File(rootJavaPackage,
                "service/HelloService.java");
        log.info("Creating HelloService.java");
        writeToFile(helloService, "HelloService.java.template", bindings);
        
        final File helloServiceImpl = new File(rootJavaPackage,
                "service/impl/HelloServiceImpl.java");
        log.info("Creating HelloServiceImpl.java");
        writeToFile(helloServiceImpl, "HelloServiceImpl.java.template",
            bindings);
    }
    
    public String getDescription() {
        return RESOURCES.getString("web.description");
    }
    
    public String getId() {
        return "web";
    }
    
    public String getName() {
        return RESOURCES.getString("web");
    }
}
